%{

#include <stdio.h>
#include "ast.h"
#include "TAC.h"
int yylex(void);
void yyerror(char *);

%}

%union
{
	int		Token;
	int		Value;//NUMBER
	char*	Stiring;//IDentifier
	past	pAst;

};

%token <Value> NUMBER		//Y_INTEGER=257,	 // 整数
%token <Stiring> IDentifier//Y_ID=256,		// 标识符
%token <Token>	Y_INT Y_VOID Y_CONST Y_IF Y_ELSE Y_WHILE Y_BREAK Y_CONTINUE Y_RETURN Y_ADD Y_SUB Y_MUL Y_DIV Y_MODULO Y_LESS Y_LESSEQ Y_GREAT Y_GREATEQ Y_NOTEQ Y_EQ Y_NOT Y_AND Y_OR Y_ASSIGN
%token <Token>  Y_LPAR Y_RPAR Y_LBRACKET Y_RBRACKET Y_LSQUARE Y_RSQUARE Y_COMMA Y_SEMICOLON
%type  <pAst>	Pro CompUnit Decl ConstDecl ConstDefs ConstDef ConstExps 
%type  <pAst>	ConstInitVal ConstInitVals VarDecl VarDecls VarDef 
%type  <pAst>	InitVal InitVals FuncDef FuncFParams FuncFParamss LVal PrimaryExp
%type  <pAst>	FuncFParam Block BlockItems BlockItem Stmt Exp Cond 
%type  <pAst>	Exps Number UnaryExp FuncRParams Expss MulExp AddExp 
%type  <pAst>	RelExp EqExp LAndExp LOrExp ConstExp Ident IntConst

%%
//任务				
Pro				:	CompUnit										{printf("Program\n");initlistmap();showAst($1, -1);buildTAC($1,-1);}
					|												{printf("empty\n");}
					;
//编译单元			
CompUnit		: 	Decl CompUnit									{$$ = newCompUnit($1, $2);}								
					| FuncDef CompUnit								{$$ = newCompUnit($1, $2);}
					| Decl											{$$ = $1;}
					| FuncDef										{$$ = $1;}
					;
//声明				
Decl			: 	ConstDecl 										{$$ = $1;}
					| VarDecl										{$$ = $1;}
					;
//常量声明				
ConstDecl		: 	Y_CONST Y_INT ConstDef Y_SEMICOLON				{$$ = newConstDecl($1, $2, $3, NULL);}
					|Y_CONST Y_INT ConstDef ConstDefs Y_SEMICOLON	{$$ = newConstDecl($1, $2, $3, $4);}
					;
//常数定义s 		
ConstDefs		:	Y_COMMA ConstDef								{$$ = $2;}
					|Y_COMMA ConstDef ConstDefs						{$$ = newConstDefs($2, $3);}
					;

//常数定义			yes//有改动
ConstDef		: 	Ident Y_ASSIGN ConstInitVal						{$$ = newConstDef($2, $1, NULL, $3);}
					|Ident ConstExps Y_ASSIGN ConstInitVal			{$$ = newConstDef($3, $1, $2, $4);}
					;
//常量表达式s		yes
ConstExps		:	Y_LSQUARE ConstExp Y_RSQUARE					{$$ = newConstExps($2, NULL);}
					|Y_LSQUARE ConstExp Y_RSQUARE ConstExps			{$$ = newConstExps($2, $4);}
					;
//常量初值			yes	//12.17	
ConstInitVal	: 	ConstExp												{$$ = $1;}
					| Y_LBRACKET								Y_RBRACKET	{$$ = newConstInitVal( NULL, NULL, NULL);}
					| Y_LBRACKET  ConstInitVal 					Y_RBRACKET	{$$ = newConstInitVal( NULL, $2, NULL);}
					| Y_LBRACKET  ConstInitVal ConstInitVals	Y_RBRACKET	{$$ = newConstInitVal( NULL, $2, $3);}
					;
//常量初值s			
ConstInitVals	:	Y_COMMA ConstInitVal							{$$ = $2;}
					|Y_COMMA ConstInitVal ConstInitVals				{$$ = newConstInitVals($2, $3);}
					;
//变量声明			yes
VarDecl			: 	Y_INT VarDef  Y_SEMICOLON						{$$ = newVarDecl($1, $2, NULL);}
					|Y_INT VarDef VarDecls Y_SEMICOLON				{$$ = newVarDecl($1, $2, $3);}
					;
//变量定义s			
VarDecls		:	Y_COMMA VarDef									{$$ = $2;}
					|Y_COMMA VarDef VarDecls						{$$ = newVarDecls($2, $3);}
					;
//变量定义			yes//12.17改
VarDef			: 	Ident 											{$$ = newVarDef(-1, $1, NULL, NULL);}
					| Ident Y_ASSIGN InitVal						{$$ = newVarDef($2, $1, NULL, $3);}
					| Ident ConstExps								{$$ = newVarDef(-1, $1, $2, NULL);}
					| Ident ConstExps Y_ASSIGN InitVal				{$$ = newVarDef($3, $1, $2, $4);}
					;
//变量初值			yes
InitVal			: 	Exp												{$$ = $1;}
					|	Y_LBRACKET 					Y_RBRACKET		{$$ = newInitVal(NULL, NULL, NULL);}
					|	Y_LBRACKET InitVal			Y_RBRACKET		{$$ = newInitVal(NULL, $2, NULL);}
					| 	Y_LBRACKET InitVal InitVals Y_RBRACKET		{$$ = newInitVal(NULL, $2, $3);}
					;
//变量初值s				
InitVals		:	Y_COMMA InitVal 								{$$ = $2;}
					|Y_COMMA InitVal InitVals						{$$ = newInitVals($2, $3);}
					;
//函数定义			yes
FuncDef			: 	Y_INT Ident Y_LPAR Y_RPAR Block					{$$ = newFuncDef($1, $2, NULL, $5);}
					|Y_INT Ident Y_LPAR FuncFParams Y_RPAR Block	{$$ = newFuncDef($1, $2, $4, $6);}
					|Y_VOID Ident Y_LPAR Y_RPAR Block				{$$ = newFuncDef($1, $2, NULL, $5);}
					|Y_VOID Ident Y_LPAR FuncFParams Y_RPAR Block	{$$ = newFuncDef($1, $2, $4, $6);}
					;

//函数形参表		
FuncFParams		: 	FuncFParam										{$$ = newFuncFParams($1, NULL);}
					|FuncFParam FuncFParamss						{$$ = newFuncFParams($1, $2);}
					;
//函数形参ss		
FuncFParamss	:	 Y_COMMA FuncFParam								{$$ = $2;}
					|Y_COMMA FuncFParam FuncFParamss				{$$ = newFuncFParamss($2, $3);}
//函数形参			yes
FuncFParam		: 	Y_INT Ident 									{$$ = newFuncFParam($1,-1, $2,NULL);}
					|Y_INT Ident Y_LSQUARE Y_RSQUARE 				{$$ = newFuncFParam($1,1, $2,NULL);}
					|Y_INT Ident Exps								{$$ = newFuncFParam($1,0, $2,$3);}
					|Y_INT Ident Y_LSQUARE Y_RSQUARE Exps 			{$$ = newFuncFParam($1,1, $2,$5);}
					;
//语句块			yes
Block			: 	Y_LBRACKET BlockItems Y_RBRACKET				{$$ = newBlock($2);}
					;
//语句块项s			
BlockItems		:	BlockItem										{$$ = $1;}
					|BlockItem BlockItems							{$$ = newBlockItems($1, $2);}
					;
//语句块项			
BlockItem		: 	Decl 											{$$ = $1;}
					|Stmt											{$$ = $1;}
					;
//语句				
Stmt			: 	LVal Y_ASSIGN Exp Y_SEMICOLON					{$$ = newStmt(-1, $2, $1, NULL,$3);}
					|Y_SEMICOLON									{$$ = NULL;}
					|Exp Y_SEMICOLON  								{$$ = newStmt(-1, -1, $1, NULL,NULL);}
					|Block											{$$ = $1;}
					|Y_WHILE Y_LPAR Cond Y_RPAR Stmt				{$$ = newStmt($1, -1, $3, $5,NULL);}
					|Y_IF Y_LPAR Cond Y_RPAR Stmt					{$$ = newStmt($1, -1, $3, $5,NULL);}
					|Y_IF Y_LPAR Cond Y_RPAR Stmt Y_ELSE Stmt		{$$ = newStmt($1, $6, $3, $5,$7);}
					|Y_BREAK Y_SEMICOLON							{$$ = newStmt($1, -1, NULL, NULL,NULL);}
					|Y_CONTINUE Y_SEMICOLON							{$$ = newStmt($1, -1, NULL, NULL,NULL);}
					|Y_RETURN Exp Y_SEMICOLON						{$$ = newStmt($1, -1, $2, NULL,NULL);}
					|Y_RETURN Y_SEMICOLON							{$$ = newStmt($1, -1, NULL, NULL,NULL);}
					;
//表达式			
Exp				: 	AddExp								{$$ = $1;}
					;
//条件表达式		
Cond			: 	LOrExp								{$$ = $1;}
					;
//左值表达式		yes
LVal			: 	Ident								{$$ = newLVal($1, NULL);}
					|Ident Exps							{$$ = newLVal($1, $2);}
					;
//表达式s			yes
Exps			:	Y_LSQUARE Exp Y_RSQUARE				{$$ = newExps($2, NULL);}
					|Y_LSQUARE Exp Y_RSQUARE Exps		{$$ = newExps($2, $4);}
					;
//基本表达式		
PrimaryExp		: 	Y_LPAR Exp Y_RPAR 					{$$ = $2;}
					| LVal 								{$$ = $1;}
					| Number							{$$ = $1;}
					;
//数值				y
Number			: 	IntConst							{$$ = newNumber($1);}
					;
//一元表达式		yes&no
UnaryExp		: 	PrimaryExp 							{$$ = $1;}
					| Ident Y_LPAR Y_RPAR				{$$ = newUnaryExp(-1, $1, NULL);}
					| Ident Y_LPAR FuncRParams Y_RPAR	{$$ = newUnaryExp(-1, $1, $3);}
					| Y_ADD UnaryExp					{$$ = newUnaryExp($1, $2, NULL);}
					| Y_SUB UnaryExp					{$$ = newUnaryExp($1, $2, NULL);}
					| Y_NOT UnaryExp					{$$ = newUnaryExp($1, $2, NULL);}
					;

//函数实参表		
FuncRParams		: 	Exp							{$$ = newFuncRParams($1, NULL);}
					|FuncRParams Y_COMMA Exp	{$$ = newFuncRParams($3, $1);}//?{$$ = newFuncRParams($1, newFuncRParams($2, NULL));}
					;
//表达式ss			
Expss			: 	Y_COMMA Exp 				{$$ = $2;} 
					|Y_COMMA Exp Expss			{$$ = newExpss($2, $3);} 
					;
//乘除模表达式		yes
MulExp			: 	UnaryExp 					{$$ = $1;} 
					| MulExp Y_MUL UnaryExp		{$$ = newExpr($2, $1, $3);} 
					| MulExp Y_DIV UnaryExp		{$$ = newExpr($2, $1, $3);} 
					| MulExp Y_MODULO UnaryExp	{$$ = newExpr($2, $1, $3);} 
					;
//加减表达式		yes
AddExp			: 	MulExp 						{$$ = $1;} 
					| MulExp Y_ADD AddExp		{$$ = newExpr($2, $1, $3);} 
					| MulExp Y_SUB AddExp		{$$ = newExpr($2, $1, $3);} 
					;
//关系表达式		y
RelExp			: 	AddExp 						{$$ = $1;} 
					| RelExp Y_LESS AddExp		{$$ = newExpr($2, $1, $3);} 
					| RelExp Y_GREAT AddExp		{$$ = newExpr($2, $1, $3);} 
					| RelExp Y_LESSEQ AddExp	{$$ = newExpr($2, $1, $3);} 
					| RelExp Y_GREATEQ AddExp	{$$ = newExpr($2, $1, $3);} 
					;
//相等性表达式		y
EqExp			: 	RelExp 						{$$ = $1;} 
					| EqExp Y_EQ RelExp			{$$ = newExpr($2, $1, $3);} 
					| EqExp Y_NOTEQ RelExp		{$$ = newExpr($2, $1, $3);} 
					;
//逻辑与表达式		y
LAndExp			: 	EqExp 						{$$ = $1;} 
					| LAndExp Y_AND EqExp		{$$ = newExpr($2, $1, $3);} 
					;
//逻辑或表达式		y
LOrExp			: 	LAndExp 					{$$ = $1;} 
					| LOrExp Y_OR LAndExp		{$$ = newExpr($2, $1, $3);} 
					;
//常量表达式		y
ConstExp		: 	AddExp						{$$ = $1;} 
					;
//标识符			yes
Ident			: 	IDentifier					{$$ = newString($1);}
					;
//数值常量			yes
IntConst		:	NUMBER						{$$ = newNum($1);}
					;
%%

